#include <openssl/ossl_typ.h>
#include <openssl/evp.h>
#include <stdio.h>
#include "e_os.h"
#include "hard.h"
#include "sec_common.h"

sm1_ecb_ssl_hard_test(int fd)
{
	volatile unsigned char *mem;
	struct cipher_api capi;
	unsigned int max_len = max_crypto_len;
	unsigned char *out,*dt;
	unsigned int i;
	int keykind;
	int ret=0;

	for(keykind=0;keykind<2;keykind++)
	{
		capi.alg = SM1;
		capi.type  = ECB;
		capi.as = INITFINAL;

		if(keykind==0)
		{
			capi.key_len = 32;
			capi.opt =0;
		}
		else if(keykind==1)
		{
			capi.key_len = 48;
			capi.opt = AAI_SK;
		}
		capi.iv_len = 16;
		capi.data_len = (( 0x10|(unsigned)(rand()) )&(max_crypto_len/2-1))&0xfffffff0 ;

		debug("max_crypto_len is 0x%x,data_len is 0x%x,key_size is 0x%x\n",max_len,capi.data_len,capi.key_len);

		mem = malloc(CHEAD_SIZE+capi.key_len+capi.iv_len+capi.data_len);
		out = malloc(capi.data_len);
		dt = malloc(capi.data_len);


		set_rand_mem((void *)(mem+CHEAD_SIZE),capi.key_len);
		set_rand_mem((void *)(mem+CHEAD_SIZE+capi.key_len),capi.iv_len);
		set_rand_mem((void *)(mem+CHEAD_SIZE+capi.key_len+capi.iv_len),capi.data_len);

		memcpy((void *)dt,(void *)(mem+CHEAD_SIZE+capi.key_len+capi.iv_len),capi.data_len);

	/////////////////////////////////////////////////////////////////////////////
	//enc
	/////////////////////////////////////////////////////////////////////////////

		capi.opt = (capi.opt &(~DIR_MASK)) | ENC;

		memcpy((void *)mem,(void *)(&capi),CHEAD_SIZE);

		ioctl(fd,_IOC(0x00,CCP903T_PCIE_MAGIC, ACLASS_CIPHER,CHEAD_SIZE+capi.key_len+capi.iv_len+capi.data_len),mem);
		while(!(mem[3]&DDONE_MASK));

		if( memcmp((void *)dt,(void *)(mem+CHEAD_SIZE+capi.key_len+capi.iv_len),capi.data_len))		//after enc,the data is not oringe
		{
			ret = 1;
		}


	/////////////////////////////////////////////////////////////////////////////
	//dec
	/////////////////////////////////////////////////////////////////////////////

		capi.opt = (capi.opt &(~DIR_MASK)) | DEC;

		memcpy((void *)mem,(void *)(&capi),CHEAD_SIZE);

		ioctl(fd,_IOC(0x00,CCP903T_PCIE_MAGIC, ACLASS_CIPHER,CHEAD_SIZE+capi.key_len+capi.iv_len+capi.data_len),mem);
		while(!(mem[3]&DDONE_MASK));

		if(!memcmp((void *)dt,(void *)(mem+CHEAD_SIZE+capi.key_len+capi.iv_len),capi.data_len) && ret ==1)
			debug("sm1_ecb_ssl_hard test ok! keykind is %d\n",keykind);
		else
		{
			errout("sm1_ecb_ssl_hard  test error!keykind is %d\n",keykind);
			fail_prosess();
		}

		free((void *)out);
		free((void *)mem);
		free((void *)dt);
	}

}

sm1_cbc_ssl_hard_key32_speed(int fd)
{
	int tcnt=100,MNUM=1000;
	volatile unsigned char *mem;
	struct cipher_api capi;
	unsigned int max_len = max_crypto_len; //16k
	unsigned char *out,*dt,iv_tmp[16];
	unsigned int i;
	struct timeval tv1,tv2;

	int cpid;
	int semval;
	int time,speed;

	capi.alg = SM1;
	capi.type  = CBC;
	capi.as = INITFINAL;
	capi.key_len = 32;
	capi.iv_len = 16;
	capi.data_len = (max_crypto_len-100)&0xfffffff0;

	debug("max_crypto_len is 0x%x,data_len is 0x%x,key_size is 0x%x\n",max_len,capi.data_len,capi.key_len);

	for(i=0;i<tcnt-1;i++)
	{
		cpid = fork();
		if(cpid==0)
			break;
	}
//	printf("i = %d\n",i);
	mem= malloc(CHEAD_SIZE+capi.key_len+capi.iv_len+capi.data_len);

/////////////////////////////////////////////////////////////////////////////
//enc
/////////////////////////////////////////////////////////////////////////////

	capi.opt = ENC;

	memcpy((void *)mem,(void *)(&capi),CHEAD_SIZE);

	if(cpid==0)
	{
		do{
			sem_getvalue(usem->sem,&semval);
		}
		while(semval==1);
	}else{
		sem_wait(usem->sem);
		gettimeofday(&tv1, NULL);
	}

	for(i=0;i<MNUM;i++)
	{

		ioctl(fd,_IOC(0x00,CCP903T_PCIE_MAGIC, ACLASS_CIPHER,CHEAD_SIZE+capi.key_len+capi.iv_len+capi.data_len),mem);

		while(!(mem[3]&DDONE_MASK));
	}

	sem_wait(dsem->sem);

	if(cpid==0)
	{
		free((void *)mem);
		exit(0);
	}else{
		do{
			sem_getvalue(dsem->sem,&semval);
		}
		while(semval!=(MAX_SEM_CNT-tcnt));
		gettimeofday(&tv2, NULL);
		free((void *)mem);
	}
	sem_post(usem->sem);

	for(i=0;i<tcnt;i++)
	{
		sem_post(dsem->sem);
	}

	time = (tv2.tv_sec-tv1.tv_sec)*1000000+tv2.tv_usec-tv1.tv_usec;

	speed = MNUM*tcnt*capi.data_len/time;
	speed*=8;

	spd_dbg("%s,CBC encrypt data_len %d,tcnt %d,speed is %dMbps,time %d us\n",__FILE__,capi.data_len,tcnt,speed,time);

/////////////////////////////////////////////////////////////////////////////
//dec
/////////////////////////////////////////////////////////////////////////////
	for(i=0;i<tcnt-1;i++)
	{
		cpid = fork();
		if(cpid==0)
			break;
	}

	mem= malloc(CHEAD_SIZE+capi.key_len+capi.iv_len+capi.data_len);

	capi.opt = DEC;

	memcpy((void *)mem,(void *)(&capi),CHEAD_SIZE);

	if(cpid==0)
	{
		do{
			sem_getvalue(usem->sem,&semval);
		}
		while(semval==1);
	}else{
		sem_wait(usem->sem);
		gettimeofday(&tv1, NULL);
	}

	for(i=0;i<MNUM;i++)
	{
		ioctl(fd,_IOC(0x00,CCP903T_PCIE_MAGIC, ACLASS_CIPHER,CHEAD_SIZE+capi.key_len+capi.iv_len+capi.data_len),mem);

		while(!(mem[3]&DDONE_MASK));
	}
	sem_wait(dsem->sem);

	if(cpid==0)
	{
		free((void *)mem);
		exit(0);
	}else{
		do{
			sem_getvalue(dsem->sem,&semval);
		}
		while(semval!=(MAX_SEM_CNT-tcnt));
		gettimeofday(&tv2, NULL);
		free((void *)mem);
	}

	sem_post(usem->sem);
	for(i=0;i<tcnt;i++)
	{
		sem_post(dsem->sem);
	}

	time = (tv2.tv_sec-tv1.tv_sec)*1000000+tv2.tv_usec-tv1.tv_usec;

	speed = MNUM*tcnt*capi.data_len/time;
	speed*=8;

	spd_dbg("%s,CBC decrypt data_len %d,tcnt %d,speed is %dMbps,time %d us\n",__FILE__,capi.data_len,tcnt,speed,time);

}

sm1_cbc_ssl_hard_test(int fd)
{
	volatile unsigned char *mem;
	struct cipher_api capi;
	unsigned int max_len = max_crypto_len;
	unsigned char *out,*dt,iv_tmp[16];
	unsigned int i;
	int keykind;
	int ret=0;

	for(keykind=0;keykind<2;keykind++)
	{
		capi.alg = SM1;
		capi.type  = CBC;
		capi.as = INITFINAL;

		if(keykind==0)
		{
			capi.key_len = 32;
			capi.opt =0;
		}
		else if(keykind==1)
		{
			capi.key_len = 48;
			capi.opt =AAI_SK;
		}
		capi.iv_len = 16;
		capi.data_len = (( 0x10|(unsigned)(rand()) )&(max_crypto_len/2-1))&0xfffffff0 ;

		debug("max_crypto_len is 0x%x,data_len is 0x%x,key_size is 0x%x\n",max_len,capi.data_len,capi.key_len);

		mem = malloc(CHEAD_SIZE+capi.key_len+capi.iv_len+capi.data_len);
		out = malloc(capi.data_len);
		dt = malloc(capi.data_len);


		set_rand_mem((void *)(mem+CHEAD_SIZE),capi.key_len);
		set_rand_mem((void *)(mem+CHEAD_SIZE+capi.key_len),capi.iv_len);
		set_rand_mem((void *)(mem+CHEAD_SIZE+capi.key_len+capi.iv_len),capi.data_len);

		memcpy((void *)dt,(void *)(mem+CHEAD_SIZE+capi.key_len+capi.iv_len),capi.data_len);
		memcpy((void *)iv_tmp,(void *)(mem+CHEAD_SIZE+capi.key_len),capi.iv_len);

	/////////////////////////////////////////////////////////////////////////////
	//enc
	/////////////////////////////////////////////////////////////////////////////

		capi.opt = (capi.opt &(~DIR_MASK)) | ENC;

		memcpy((void *)mem,(void *)(&capi),CHEAD_SIZE);

		ioctl(fd,_IOC(0x00,CCP903T_PCIE_MAGIC, ACLASS_CIPHER,CHEAD_SIZE+capi.key_len+capi.iv_len+capi.data_len),mem);
		while(!(mem[3]&DDONE_MASK));


		if( memcmp((void *)dt,(void *)(mem+CHEAD_SIZE+capi.key_len+capi.iv_len),capi.data_len))		//after enc,the data is not oringe
		{
			ret = 1;
		}

	/////////////////////////////////////////////////////////////////////////////
	//dec
	/////////////////////////////////////////////////////////////////////////////

		capi.opt = (capi.opt &(~DIR_MASK)) | DEC;

		memcpy((void *)mem,(void *)(&capi),CHEAD_SIZE);
		memcpy((void *)(mem+CHEAD_SIZE+capi.key_len),(void *)(iv_tmp),capi.iv_len);

		ioctl(fd,_IOC(0x00,CCP903T_PCIE_MAGIC, ACLASS_CIPHER,CHEAD_SIZE+capi.key_len+capi.iv_len+capi.data_len),mem);
		while(!(mem[3]&DDONE_MASK));

		if(!memcmp((void *)dt,(void *)(mem+CHEAD_SIZE+capi.key_len+capi.iv_len),capi.data_len) && ret==1)
			debug("sm1_cbc_ssl_hard test ok! keykind is %d\n",keykind);
		else
		{
			errout("sm1_cbc_ssl_hard  test error!keykind is %d\n",keykind);
			fail_prosess();
		}

		free((void *)out);
		free((void *)mem);
		free((void *)dt);
	}

}

sm1_ctr_ssl_hard_test(int fd)
{
	volatile unsigned char *mem;
	struct cipher_api capi;
	unsigned int max_len = max_crypto_len;
	unsigned char *out,*dt,iv_tmp[32];
	unsigned int i;
	int keykind;
	int ret=0;

	for(keykind=0;keykind<2;keykind++)
	{
		capi.alg = SM1;
		capi.type  = CTR;
		capi.as = INITFINAL;

		if(keykind==0)
		{
			capi.key_len = 32;
			capi.opt =0;
		}
		else if(keykind==1)
		{
			capi.key_len = 48;
			capi.opt =AAI_SK;
		}
		capi.iv_len = 16*2;
		capi.data_len = (( 0x10|(unsigned)(rand()) )&(max_crypto_len/2-1))&0xfffffff0 ;

		debug("max_crypto_len is 0x%x,data_len is 0x%x,key_size is 0x%x\n",max_len,capi.data_len,capi.key_len);

		mem = malloc(CHEAD_SIZE+capi.key_len+capi.iv_len+capi.data_len);
		out = malloc(capi.data_len);
		dt = malloc(capi.data_len);


		set_rand_mem((void *)(mem+CHEAD_SIZE),capi.key_len);
		set_rand_mem((void *)(mem+CHEAD_SIZE+capi.key_len),capi.iv_len);
		set_rand_mem((void *)(mem+CHEAD_SIZE+capi.key_len+capi.iv_len),capi.data_len);

		memcpy((void *)dt,(void *)(mem+CHEAD_SIZE+capi.key_len+capi.iv_len),capi.data_len);
		memcpy((void *)iv_tmp,(void *)(mem+CHEAD_SIZE+capi.key_len),capi.iv_len);

	/////////////////////////////////////////////////////////////////////////////
	//enc
	/////////////////////////////////////////////////////////////////////////////

		capi.opt = (capi.opt &(~DIR_MASK)) | ENC;

		memcpy((void *)mem,(void *)(&capi),CHEAD_SIZE);

		ioctl(fd,_IOC(0x00,CCP903T_PCIE_MAGIC, ACLASS_CIPHER,CHEAD_SIZE+capi.key_len+capi.iv_len+capi.data_len),mem);
		while(!(mem[3]&DDONE_MASK));


		if( memcmp((void *)dt,(void *)(mem+CHEAD_SIZE+capi.key_len+capi.iv_len),capi.data_len))		//after enc,the data is not oringe
		{
			ret = 1;
		}

	/////////////////////////////////////////////////////////////////////////////
	//dec
	/////////////////////////////////////////////////////////////////////////////

		capi.opt = (capi.opt &(~DIR_MASK)) | DEC;

		memcpy((void *)mem,(void *)(&capi),CHEAD_SIZE);
		memcpy((void *)(mem+CHEAD_SIZE+capi.key_len),(void *)iv_tmp,capi.iv_len);

		ioctl(fd,_IOC(0x00,CCP903T_PCIE_MAGIC, ACLASS_CIPHER,CHEAD_SIZE+capi.key_len+capi.iv_len+capi.data_len),mem);
		while(!(mem[3]&DDONE_MASK));

		if(!memcmp((void *)dt,(void *)(mem+CHEAD_SIZE+capi.key_len+capi.iv_len),capi.data_len) && ret==1)
			debug("sm1_cbc_ssl_hard test ok! keykind is %d\n",keykind);
		else
		{
			errout("sm1_cbc_ssl_hard  test error!keykind is %d\n",keykind);
			fail_prosess();
		}

		free((void *)out);
		free((void *)mem);
		free((void *)dt);
	}

}

sm1_cfb_ssl_hard_test(int fd)
{
	volatile unsigned char *mem;
	struct cipher_api capi;
	unsigned int max_len = max_crypto_len;
	unsigned char *out,*dt,iv_tmp[16];
	unsigned int i;
	int keykind;
	int ret=0;

	for(keykind=0;keykind<2;keykind++)
	{
		capi.alg = SM1;
		capi.type  = CFB;
		capi.as = INITFINAL;

		if(keykind==0)
		{
			capi.key_len = 32;
			capi.opt =0;
		}
		else if(keykind==1)
		{
			capi.key_len = 48;
			capi.opt =AAI_SK;
		}
		capi.iv_len = 16;
		capi.data_len = (( 0x10|(unsigned)(rand()) )&(max_crypto_len/2-1))&0xfffffff0 ;

		debug("max_crypto_len is 0x%x,data_len is 0x%x,key_size is 0x%x\n",max_len,capi.data_len,capi.key_len);

		mem = malloc(CHEAD_SIZE+capi.key_len+capi.iv_len+capi.data_len);
		out = malloc(capi.data_len);
		dt = malloc(capi.data_len);


		set_rand_mem((void *)(mem+CHEAD_SIZE),capi.key_len);
		set_rand_mem((void *)(mem+CHEAD_SIZE+capi.key_len),capi.iv_len);
		set_rand_mem((void *)(mem+CHEAD_SIZE+capi.key_len+capi.iv_len),capi.data_len);

		memcpy((void *)dt,(void *)(mem+CHEAD_SIZE+capi.key_len+capi.iv_len),capi.data_len);
		memcpy((void *)iv_tmp,(void *)(mem+CHEAD_SIZE+capi.key_len),capi.iv_len);

	/////////////////////////////////////////////////////////////////////////////
	//enc
	/////////////////////////////////////////////////////////////////////////////

		capi.opt = (capi.opt &(~DIR_MASK)) | ENC;

		memcpy((void *)mem,(void *)(&capi),CHEAD_SIZE);

		ioctl(fd,_IOC(0x00,CCP903T_PCIE_MAGIC, ACLASS_CIPHER,CHEAD_SIZE+capi.key_len+capi.iv_len+capi.data_len),mem);
		while(!(mem[3]&DDONE_MASK));

		if( memcmp((void *)dt,(void *)(mem+CHEAD_SIZE+capi.key_len+capi.iv_len),capi.data_len))		//after enc,the data is not oringe
		{
			ret = 1;
		}

	/////////////////////////////////////////////////////////////////////////////
	//dec
	/////////////////////////////////////////////////////////////////////////////

		capi.opt = (capi.opt &(~DIR_MASK)) | DEC;

		memcpy((void *)mem,(void *)(&capi),CHEAD_SIZE);
		memcpy((void *)(mem+CHEAD_SIZE+capi.key_len),(void *)iv_tmp,capi.iv_len);

		ioctl(fd,_IOC(0x00,CCP903T_PCIE_MAGIC, ACLASS_CIPHER,CHEAD_SIZE+capi.key_len+capi.iv_len+capi.data_len),mem);
		while(!(mem[3]&DDONE_MASK));

		if(!memcmp((void *)dt,(void *)(mem+CHEAD_SIZE+capi.key_len+capi.iv_len),capi.data_len) && ret == 1)
			debug("sm1_cfb_ssl_hard test ok! keykind is %d\n",keykind);
		else
		{
			errout("sm1_cfb_ssl_hard  test error!keykind is %d\n",keykind);
			fail_prosess();
		}

		free((void *)out);
		free((void *)mem);
		free((void *)dt);
	}

}

sm1_ofb_ssl_hard_test(int fd)
{
	volatile unsigned char *mem;
	struct cipher_api capi;
	unsigned int max_len = max_crypto_len;
	unsigned char *out,*dt,iv_tmp[16];
	unsigned int i;
	int keykind;
	int ret=0;

	for(keykind=0;keykind<2;keykind++)
	{
		capi.alg = SM1;
		capi.type  = OFB;
		capi.as = INITFINAL;

		if(keykind==0)
		{
			capi.key_len = 32;
			capi.opt =0;
		}
		else if(keykind==1)
		{
			capi.key_len = 48;
			capi.opt =AAI_SK;
		}
		capi.iv_len = 16;
		capi.data_len = (( 0x10|(unsigned)(rand()) )&(max_crypto_len/2-1))&0xfffffff0 ;

		debug("max_crypto_len is 0x%x,data_len is 0x%x,key_size is 0x%x\n",max_len,capi.data_len,capi.key_len);

		mem = malloc(CHEAD_SIZE+capi.key_len+capi.iv_len+capi.data_len);
		out = malloc(capi.data_len);
		dt = malloc(capi.data_len);


		set_rand_mem((void *)(mem+CHEAD_SIZE),capi.key_len);
		set_rand_mem((void *)(mem+CHEAD_SIZE+capi.key_len),capi.iv_len);
		set_rand_mem((void *)(mem+CHEAD_SIZE+capi.key_len+capi.iv_len),capi.data_len);

		memcpy((void *)dt,(void *)(mem+CHEAD_SIZE+capi.key_len+capi.iv_len),capi.data_len);
		memcpy((void *)iv_tmp,(void *)(mem+CHEAD_SIZE+capi.key_len),capi.iv_len);

	/////////////////////////////////////////////////////////////////////////////
	//enc
	/////////////////////////////////////////////////////////////////////////////

		capi.opt = (capi.opt &(~DIR_MASK)) | ENC;

		memcpy((void *)mem,(void *)(&capi),CHEAD_SIZE);

		ioctl(fd,_IOC(0x00,CCP903T_PCIE_MAGIC, ACLASS_CIPHER,CHEAD_SIZE+capi.key_len+capi.iv_len+capi.data_len),mem);
		while(!(mem[3]&DDONE_MASK));

		if( memcmp((void *)dt,(void *)(mem+CHEAD_SIZE+capi.key_len+capi.iv_len),capi.data_len))		//after enc,the data is not oringe
		{
			ret = 1;
		}

	/////////////////////////////////////////////////////////////////////////////
	//dec
	/////////////////////////////////////////////////////////////////////////////

		capi.opt = (capi.opt &(~DIR_MASK)) | DEC;

		memcpy((void *)mem,(void *)(&capi),CHEAD_SIZE);
		memcpy((void *)(mem+CHEAD_SIZE+capi.key_len),(void *)iv_tmp,capi.iv_len);

		ioctl(fd,_IOC(0x00,CCP903T_PCIE_MAGIC, ACLASS_CIPHER,CHEAD_SIZE+capi.key_len+capi.iv_len+capi.data_len),mem);
		while(!(mem[3]&DDONE_MASK));

		if(!memcmp((void *)dt,(void *)(mem+CHEAD_SIZE+capi.key_len+capi.iv_len),capi.data_len) && ret == 1)
			debug("sm1_ofb_ssl_hard test ok! keykind is %d\n",keykind);
		else
		{
			errout("sm1_ofb_ssl_hard  test error!keykind is %d\n",keykind);
			fail_prosess();
		}

		free((void *)out);
		free((void *)mem);
		free((void *)dt);
	}

}
